
import * as THREE from 'three';
import React from 'react';
import { ToolType } from '../constants/ToolType';
import threeToMap from 'tools/fns/threeToMap';
import Controller from "../Controller";

/** 选取工具 */
export default function useSelect(controller: Controller) {

    /** 选中得工具 */
    const selectedTool = controller.useMemo(s => s.selectedTool, []);

    /** 原件字典 */
    const elementMap = controller.useMemo(s => s.elementMap, []);

    /** 原件字典 */
    const elementUuidMap = React.useMemo(() => {
        const map: { [key: string]: string } = {}
        elementMap.forEach(e => {
            const uuid = e.getObject3D()?.uuid
            if (uuid) {
                map[uuid] = uuid
            }
        })
        return map;
    }, [elementMap]);

    /** canvas 容器 */
    const cont = controller.useMemo(s => s.cont, []);

    /** 相机 */
    const camera = controller.useMemo(s => s.camera, []);

    /** 场景 */
    const scene = controller.useMemo(s => s.scene, []);

    /** 检验是不是 原件 */
    const check = React.useCallback((item?: THREE.Object3D | null): undefined | THREE.Object3D => {
        if (!item) return undefined
        if (item && item.uuid && elementUuidMap[item.uuid]) {
            return item;
        } else {
            return check(item?.parent);
        }
    }, [elementUuidMap])

    React.useEffect(() => {
        if (selectedTool !== ToolType.选取 || !cont) return;

        const width = cont.offsetWidth;
        const height = cont.offsetHeight;

        /*射线投射器*/
        const mouse = new THREE.Vector2();

        function onMouseDown(event: MouseEvent) {
            if (!camera || !scene) return;

            mouse.x = (event.clientX / width) * 2 - 1;
            mouse.y = -(event.clientY / height) * 2 + 1;

            const vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(camera);

            //将平面坐标系转为世界坐标系
            const raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());

            //得到点击的几何体
            const raycasters = raycaster.intersectObjects(scene.children);

            /** 点击的原件 */
            const el = (() => {
                for (let i = 0; i < raycasters.length; i++) {
                    const item = check(raycasters[i].object);
                    if (item) {
                        return item
                    }
                }
            })()
            if (!el) return;

            controller.run(async s => { s.selectedElementUuid = threeToMap(elementMap, el.uuid) })
        }

        cont.addEventListener("mousedown", onMouseDown, false);

        return () => {
            cont.removeEventListener("mousedown", onMouseDown, false)
        }
    }, [camera, check, cont, controller, elementMap, scene, selectedTool])
}